#lang racket


(require "global.rkt")
(require "autocad/main.rkt")
(require "rhinoceros3d/main.rkt")

(provide (prefix-out ac: (all-from-out "autocad/main.rkt"))
         (all-from-out "rhinoceros3d/main.rkt"))

(provide backend
         backend-in
         backend-out
         
         with-backend
         with-backend-in
         with-backend-out)


(define autocad-backend #f)
(define rhino-backend #f)

(define (ensure-autocad-backend)
  (if autocad-backend
      autocad-backend
      (set! autocad-backend (load-autocad-backend))))

(define (ensure-rhino-backend)
  (if rhino-backend
      rhino-backend
      (set! rhino-backend (load-rhino-backend))))


(define (backend-fn cad autocad-fn rhino-fn)
  (cond ((string=? cad "autocad") (autocad-fn))
        ((string=? cad "rhino") (rhino-fn))
        (else (error 'backend-fn "Available backends are autocad and rhino"))))

(define (backend cad)
  (backend-fn
   cad
   (λ ()
     (set-current-in-backend! (ensure-autocad-backend))
     (set-current-out-backend! (ensure-autocad-backend)))
   (λ ()
     (set-current-in-backend! (ensure-rhino-backend))
     (set-current-out-backend! (ensure-rhino-backend)))))

(define (backend-in cad)
  (backend-fn
   cad
   (λ () (set-current-in-backend! (ensure-autocad-backend)))
   (λ () (set-current-in-backend! (ensure-rhino-backend)))))

(define (backend-out cad)
  (backend-fn
   cad
   (λ () (set-current-out-backend! (ensure-autocad-backend)))
   (λ () (set-current-out-backend! (ensure-rhino-backend)))))


(define (ensure-backend cad)
  (backend-fn
   cad
   (λ () (ensure-autocad-backend))
   (λ () (ensure-rhino-backend))))

(define-syntax with-backend
  (syntax-rules ()
    ((_ cad body ...)
     (parameterize ((current-in-backend (ensure-backend cad))
                    (current-out-backend (ensure-backend cad)))
       body ...))))

(define-syntax with-backend-in
  (syntax-rules ()
    ((_ cad body ...)
     (parameterize ((current-in-backend (ensure-backend cad)))
       body ...))))

(define-syntax with-backend-out
  (syntax-rules ()
    ((_ cad body ...)
     (parameterize ((current-out-backend (ensure-backend cad)))
       body ...))))